import { ref, onMounted, onUnmounted, watch, type Ref, isRef } from "vue";
import L, {
  type Map,
  type LatLngExpression,
  type Layer,
  type IconOptions
} from "leaflet";
import "leaflet-draw";
import "leaflet/dist/leaflet.css";
import "leaflet-draw/dist/leaflet.draw.css";

// 绘制模式枚举
export type DrawingMode =
  | "marker"
  | "polyline"
  | "circle"
  | "rectangle"
  | "polygon"
  | "none";

// 绘制状态枚举
export type DrawingState =
  | "idle"
  | "drawing"
  | "editing"
  | "completed"
  | "error";

// 绘制对象类型
export type DrawingObjectType =
  | "marker"
  | "polyline"
  | "circle"
  | "rectangle"
  | "polygon";

// 绘制点信息
export interface DrawingPoint {
  /** 点ID */
  id: string | number;
  /** 纬度 */
  lat: number;
  /** 经度 */
  lng: number;
  /** 点名称 */
  name?: string;
  /** 点描述 */
  description?: string;
  /** 自定义图标 */
  icon?: IconOptions;
  /** 点样式 */
  style?: {
    color?: string;
    size?: number;
    shape?: "circle" | "square" | "custom";
    label?: string;
    labelStyle?: { color?: string; fontSize?: string; fontWeight?: string };
  };
}

// 绘制对象属性
export interface DrawingObject {
  /** 对象ID */
  id: string;
  /** 对象类型 */
  type: DrawingObjectType;
  /** 对象坐标 */
  latlngs: LatLngExpression[] | LatLngExpression;
  /** 对象名称 */
  name?: string;
  /** 对象描述 */
  description?: string;
  /** 对象样式 */
  style?: L.PathOptions;
  /** 关联的点信息 */
  points?: DrawingPoint[];
  /** 创建时间 */
  createdAt: Date;
  /** 自定义数据 */
  data?: Record<string, any>;
}

// 绘制选项
export interface DrawingOptions {
  /** 启用的绘制模式 */
  enabledModes?: DrawingMode[];
  /** 默认绘制模式 */
  defaultMode?: DrawingMode;
  /** 绘制样式 */
  style?: {
    marker?: {
      icon?: IconOptions;
      defaultStyle?: L.PathOptions;
    };
    polyline?: L.PathOptions;
    circle?: L.PathOptions;
    rectangle?: L.PathOptions;
    polygon?: L.PathOptions;
  };
  /** 是否启用编辑模式 */
  enableEditing?: boolean;
  /** 是否启用删除功能 */
  enableDeletion?: boolean;
  /** 是否显示对象信息 */
  showObjectInfo?: boolean;
  /** 是否启用捕捉功能 */
  enableSnapping?: boolean;
  /** 捕捉距离(像素) */
  snapDistance?: number;
}

// 绘制回调函数
export interface DrawingHooks {
  /** 绘制开始前回调 */
  onBeforeDraw?: (mode: DrawingMode) => void | Promise<void>;
  /** 绘制完成后回调 */
  onDrawComplete?: (object: DrawingObject) => void | Promise<void>;
  /** 编辑完成后回调 */
  onEditComplete?: (object: DrawingObject) => void | Promise<void>;
  /** 删除完成后回调 */
  onDeleteComplete?: (objectId: string) => void | Promise<void>;
  /** 绘制取消回调 */
  onDrawCancel?: () => void | Promise<void>;
  /** 绘制错误回调 */
  onDrawError?: (error: Error) => void | Promise<void>;
  /** 点选中回调 */
  onPointSelected?: (
    point: DrawingPoint,
    objectId: string | undefined
  ) => void | Promise<void>;
}

export function useMapDrawing(
  map: Map | Ref<Map | null>,
  options: DrawingOptions & DrawingHooks = {}
) {
  // 状
  // 态管理 - 状态机实现
  const state = ref<DrawingState>("idle");
  const currentMode = ref<DrawingMode>(options.defaultMode || "none");
  const drawnObjects = ref<Record<string, DrawingObject>>({});
  const drawControl = ref<any>(null);
  const editLayer = ref<L.FeatureGroup | null>(null);
  const currentObject = ref<DrawingObject | null>(null);
  const activeObjectId = ref<string | null>(null);

  // 默认配置
  const defaultOptions: Required<DrawingOptions> = {
    enabledModes: ["marker", "polyline", "circle", "rectangle", "polygon"],
    defaultMode: "none",
    style: {
      marker: {
        icon: {
          iconSize: [30, 30],
          iconAnchor: [15, 15],
          iconUrl: "/src/assets/marker-icon.png"
        },
        defaultStyle: {
          color: "#ff0000",
          weight: 2,
          opacity: 0.8
        }
      },
      polyline: {
        color: "#3388ff",
        weight: 4,
        opacity: 0.7,
        dashArray: "5, 10"
      },
      circle: {
        color: "#ff9900",
        weight: 4,
        opacity: 0.7,
        fillOpacity: 0.2
      },
      rectangle: {
        color: "#00cc66",
        weight: 4,
        opacity: 0.7,
        fillOpacity: 0.2
      },
      polygon: {
        color: "#cc00cc",
        weight: 4,
        opacity: 0.7,
        fillOpacity: 0.2
      }
    },
    enableEditing: true,
    enableDeletion: true,
    showObjectInfo: true,
    enableSnapping: true,
    snapDistance: 15
  };

  // 合并配置
  const mergedOptions = { ...defaultOptions, ...options };

  // 状态转换表
  const stateTransitions: Record<DrawingState, DrawingState[]> = {
    idle: ["drawing", "editing", "error"],
    drawing: ["idle", "completed", "error"],
    editing: ["idle", "error"],
    completed: ["idle", "editing", "error"],
    error: ["idle", "drawing"]
  };

  // 状态转换方法
  const transitionState = async (newState: DrawingState, error?: Error) => {
    const currentState = state.value;

    // 检查状态转换是否合法
    if (!stateTransitions[currentState].includes(newState)) {
      const err = new Error(`不允许从 ${currentState} 转换到 ${newState}`);
      console.error("状态转换错误:", err);
      options.onDrawError?.(err);
      state.value = "error";
      return false;
    }

    // 执行状态变更
    state.value = newState;

    // 错误状态处理
    if (newState === "error" && error) {
      console.error("绘制错误:", error);
      options.onDrawError?.(error);
    }
    return true;
  };

  // 初始化绘制控件
  const initDrawControl = (mapInstance: Map) => {
    // 创建要素组用于存储绘制的对象
    editLayer.value = L.featureGroup().addTo(mapInstance);

    // 配置绘制选项
    const drawOptions: any = {
      position: "topleft",
      draw: {
        marker: mergedOptions.enabledModes?.includes("marker")
          ? {
              icon: L.icon(mergedOptions.style?.marker?.icon),
              draggable: true
            }
          : false,
        polyline: mergedOptions.enabledModes?.includes("polyline")
          ? {
              ...mergedOptions.style?.polyline,
              allowIntersection: false,
              drawError: {
                color: "#e17055",
                message: "<strong>错误:</strong> 线段不能相交!"
              },
              showLength: true
            }
          : false,
        circle: mergedOptions.enabledModes?.includes("circle")
          ? {
              ...mergedOptions.style?.circle,
              metric: true,
              feet: false,
              nautical: false
            }
          : false,
        rectangle: mergedOptions.enabledModes?.includes("rectangle")
          ? {
              ...mergedOptions.style?.rectangle
            }
          : false,
        polygon: mergedOptions.enabledModes?.includes("polygon")
          ? {
              ...mergedOptions.style?.polygon,
              allowIntersection: false,
              drawError: {
                color: "#e17055",
                message: "<strong>错误:</strong> 多边形不能相交!"
              },
              showArea: true
            }
          : false,
        circlemarker: false // 禁用圆形标记
      },
      edit:
        mergedOptions.enableEditing || mergedOptions.enableDeletion
          ? {
              featureGroup: editLayer.value,
              edit: mergedOptions.enableEditing,
              remove: mergedOptions.enableDeletion
            }
          : false
    };

    // 添加捕捉功能
    if (mergedOptions.enableSnapping && L.Edit.Snap) {
      drawOptions.snap = {
        enabled: true,
        distance: mergedOptions.snapDistance
      };
    }

    // 创建绘制控件
    drawControl.value = new L.Control.Draw(drawOptions).addTo(mapInstance);

    // 绑定绘制事件
    mapInstance.on(L.Draw.Event.CREATED, handleDrawCreated);
    mapInstance.on(L.Draw.Event.EDITED, handleDrawEdited);
    mapInstance.on(L.Draw.Event.DELETED, handleDrawDeleted);
    mapInstance.on(L.Draw.Event.DRAWSTART, handleDrawStart);
    mapInstance.on(L.Draw.Event.DRAWSTOP, handleDrawStop);
    mapInstance.on(L.Draw.Event.EDITSTART, handleEditStart);
    mapInstance.on(L.Draw.Event.EDITSTOP, handleEditStop);
  };

  // 处理绘制创建事件
  const handleDrawCreated = async (e: any) => {
    const type = e.layerType;
    const layer = e.layer;

    if (!editLayer.value) return;

    // 将图层添加到要素组
    editLayer.value.addLayer(layer);

    // 创建绘制对象
    const drawingObject = createDrawingObject(type, layer);

    // 保存到绘制对象列表
    drawnObjects.value[drawingObject.id] = drawingObject;
    currentObject.value = drawingObject;
    activeObjectId.value = drawingObject.id;

    // 触发绘制完成回调
    options.onDrawComplete?.(drawingObject);

    // 更新状态
    transitionState("completed");
  };

  // 处理绘制编辑事件
  const handleDrawEdited = (e: any) => {
    const layers = e.layers;

    layers.eachLayer((layer: any) => {
      // 查找对应的绘制对象
      const objectId = layer._leaflet_id.toString();
      const drawingObject = drawnObjects.value[objectId];

      if (drawingObject) {
        // 更新坐标
        drawingObject.latlngs = getLayerLatLngs(layer);
        drawingObject.style = getLayerStyle(layer, drawingObject.type);

        // 触发编辑完成回调
        options.onEditComplete?.(drawingObject);
        currentObject.value = drawingObject;
      }
    });
  };

  // 处理绘制删除事件
  const handleDrawDeleted = (e: any) => {
    const layers = e.layers;

    layers.eachLayer((layer: any) => {
      const objectId = layer._leaflet_id.toString();

      // 从绘制对象列表中删除
      if (drawnObjects.value[objectId]) {
        delete drawnObjects.value[objectId];

        // 如果删除的是当前对象，重置当前对象
        if (activeObjectId.value === objectId) {
          currentObject.value = null;
          activeObjectId.value = null;
        }

        // 触发删除完成回调
        options.onDeleteComplete?.(objectId);
      }
    });
  };

  // 处理绘制开始事件
  const handleDrawStart = async (e: any) => {
    const mode = e.layerType as DrawingMode;
    currentMode.value = mode;

    // 触发绘制开始前回调
    await options.onBeforeDraw?.(mode);

    transitionState("drawing");
  };

  // 处理绘制停止事件
  const handleDrawStop = () => {
    if (state.value === "drawing") {
      // 如果绘制被取消
      options.onDrawCancel?.();
      transitionState("idle");
    }
  };

  // 处理编辑开始事件
  const handleEditStart = () => {
    transitionState("editing");
  };

  // 处理编辑停止事件
  const handleEditStop = () => {
    transitionState("idle");
  };

  // 创建绘制对象
  const createDrawingObject = (type: string, layer: any): DrawingObject => {
    const id = layer._leaflet_id.toString();
    const now = new Date();

    // 根据类型获取坐标
    const latlngs = getLayerLatLngs(layer);

    // 根据类型创建不同的绘制对象
    const drawingObject: DrawingObject = {
      id,
      type: type as DrawingObjectType,
      latlngs,
      createdAt: now,
      style: getLayerStyle(layer, type as DrawingObjectType)
    };

    // 如果是标记点，添加点信息
    if (type === "marker") {
      const latlng = latlngs as LatLngExpression;
      const pointId = `point-${id}`;
      drawingObject.points = [createDefaultPoint(latlng, pointId)];

      // 添加点点击事件
      layer.on("click", () => {
        const point = drawingObject.points?.[0];
        if (point) {
          options.onPointSelected?.(point, drawingObject.id);
        }
      });
    }

    return drawingObject;
  };

  // 创建默认点信息
  const createDefaultPoint = (
    latlng: LatLngExpression,
    id: string
  ): DrawingPoint => {
    const lat = Array.isArray(latlng) ? latlng[0] : (latlng as L.LatLng).lat;
    const lng = Array.isArray(latlng) ? latlng[1] : (latlng as L.LatLng).lng;

    return {
      id,
      lat: lat as number,
      lng: lng as number,
      name: `标记点 ${id}`,
      style: {
        color: mergedOptions.style?.marker?.defaultStyle?.color || "#ff0000",
        size: 10,
        shape: "circle",
        label: "P",
        labelStyle: { color: "#ffffff", fontSize: "12px", fontWeight: "bold" }
      }
    };
  };

  // 获取图层坐标
  const getLayerLatLngs = (
    layer: any
  ): LatLngExpression[] | LatLngExpression => {
    if (layer.getLatLng) {
      // 单点图层 (marker, circle)
      return layer.getLatLng();
    } else if (layer.getLatLngs) {
      // 多点图层 (polyline, polygon, rectangle)
      return layer.getLatLngs();
    }

    return [];
  };

  // 获取图层样式
  const getLayerStyle = (
    layer: any,
    type: DrawingObjectType
  ): L.PathOptions | undefined => {
    if (type === "marker") return undefined;

    return {
      color: layer.options.color,
      weight: layer.options.weight,
      opacity: layer.options.opacity,
      fillColor: layer.options.fillColor,
      fillOpacity: layer.options.fillOpacity,
      dashArray: layer.options.dashArray
    };
  };

  // 开始绘制
  const startDrawing = async (
    mode: DrawingMode = mergedOptions.defaultMode || "polyline"
  ) => {
    if (
      !map.value ||
      !drawControl.value ||
      !mergedOptions.enabledModes?.includes(mode)
    )
      return;

    // 触发绘制开始前回调
    await options.onBeforeDraw?.(mode);

    // 停止当前可能的绘制
    if (currentMode.value !== "none") {
      drawControl.value._toolbars.draw._activeMode?.handler.disable();
    }

    // 开始新的绘制
    currentMode.value = mode;
    drawControl.value._toolbars.draw._modes[mode].handler.enable();
  };

  // 停止绘制
  const stopDrawing = () => {
    if (!drawControl.value || currentMode.value === "none") return;

    drawControl.value._toolbars.draw._activeMode?.handler.disable();
    currentMode.value = "none";
    transitionState("idle");
  };

  // 开始编辑
  const startEditing = () => {
    if (
      !drawControl.value ||
      !mergedOptions.enableEditing ||
      editLayer.value?.getLayers().length === 0
    )
      return;

    drawControl.value._toolbars.edit._modes.edit.handler.enable();
  };

  // 停止编辑
  const stopEditing = () => {
    if (!drawControl.value || !mergedOptions.enableEditing) return;

    drawControl.value._toolbars.edit._modes.edit.handler.disable();
  };

  // 删除选中对象
  const deleteSelected = () => {
    if (
      !drawControl.value ||
      !mergedOptions.enableDeletion ||
      editLayer.value?.getLayers().length === 0
    )
      return;

    drawControl.value._toolbars.edit._modes.remove.handler.enable();
  };

  // 添加自定义点（带特殊显示和文字提醒）
  // 添加自定义点（带特殊显示和文字提醒）
  const addCustomPoint = (point: DrawingPoint): string => {
    if (!map.value || !editLayer.value) return "";

    // 创建自定义图标
    const icon = createCustomPointIcon(point);

    // 创建标记
    const marker = L.marker([point.lat, point.lng], { icon }).addTo(
      editLayer.value
    );

    // 添加弹出信息
    if (point.name || point.description || point.style?.label) {
      const popupContent = `
      <div class="custom-popup">
        ${point.name ? `<h3 style="margin: 0 0 8px 0;">${point.name}</h3>` : ""}
        ${point.description ? `<p style="margin: 0 0 8px 0;">${point.description}</p>` : ""}
        ${point.style?.label ? `<div class="popup-label" style="background: ${point.style.color}; color: ${point.style.labelStyle?.color || "#fff"}; padding: 2px 6px; border-radius: 3px; font-size: ${point.style.labelStyle?.fontSize || "12px"};">${point.style.label}</div>` : ""}
        <div class="popup-coords">
          <small>纬度: ${point.lat.toFixed(6)}</small>
          <small>经度: ${point.lng.toFixed(6)}</small>
        </div>
      </div>
    `;

      // 创建弹出窗口
      const popup = L.popup({
        maxWidth: 300,
        className: "custom-point-popup"
      }).setContent(popupContent);

      marker.bindPopup(popup);
    }

    // 添加点点击事件
    marker.on("click", () => {
      options.onPointSelected?.(point);
    });

    // 创建绘制对象并添加到列表
    const drawingObject = createDrawingObject("marker", marker);
    drawingObject.points = [point];
    drawingObject.name = point.name;
    drawingObject.description = point.description;
    drawnObjects.value[drawingObject.id] = drawingObject;

    return drawingObject.id;
  };

  // 创建自定义点图标
  const createCustomPointIcon = (point: DrawingPoint): L.Icon => {
    // 处理图标样式
    const size = point.style?.size || 30;
    const color = point.style?.color || "#ff0000";
    const shape = point.style?.shape || "circle";
    const label = point.style?.label || "";
    const labelStyle = point.style?.labelStyle || {
      color: "#ffffff",
      fontSize: "12px",
      fontWeight: "bold"
    };

    // 使用SVG创建自定义图标
    const svg = `
    <svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg">
      <${shape === "circle" ? "circle" : "rect"} 
        ${shape === "circle" ? `cx="${size / 2}" cy="${size / 2}" r="${size / 2 - 2}"` : `x="2" y="2" width="${size - 4}" height="${size - 4}" rx="${shape === "square" ? 0 : size / 4}"`} 
        fill="${color}" stroke="#ffffff" stroke-width="2" />
      ${label ? `<text x="${size / 2}" y="${size / 2 + 4}" font-size="${labelStyle.fontSize}" font-weight="${labelStyle.fontWeight}" fill="${labelStyle.color}" text-anchor="middle">${label}</text>` : ""}
    </svg>
  `;

    return L.icon({
      iconUrl:
        "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svg))),
      iconSize: [size, size],
      iconAnchor: [size / 2, size / 2],
      popupAnchor: [0, -size / 2]
    });
  };
  onMounted(() => {
    if (isRef(map)) {
      mapRef = map;
      watchMapInstance();
    } else if (map instanceof L.Map) {
      initializeMap(map);
    }
  });

  // 添加组件卸载时的清理逻辑
  onUnmounted(() => {
    if (mapInstance && drawControl.value) {
      // 移除绘制控件
      mapInstance.removeControl(drawControl.value);
      // 清除图层
      editLayer.value?.clearLayers();
      // 移除所有事件监听器
      mapInstance.off(L.Draw.Event.CREATED);
      mapInstance.off(L.Draw.Event.EDITED);
      mapInstance.off(L.Draw.Event.DELETED);
      mapInstance.off(L.Draw.Event.DRAWSTART);
      mapInstance.off(L.Draw.Event.DRAWSTOP);
      mapInstance.off(L.Draw.Event.EDITSTART);
      mapInstance.off(L.Draw.Event.EDITSTOP);
    }
  });
  return {
    addCustomPoint
  };
}

// ... 序列化绘制对象为JSON
const serializeDrawingObject = (object: DrawingObject): string => {
  const serializable = {
    ...object,
    createdAt: object.createdAt.toISOString(),
    latlngs: convertLatLngsToSerializable(object.latlngs)
  };
  return JSON.stringify(serializable);
};

// 反序列化JSON为绘制对象
const deserializeDrawingObject = (json: string): DrawingObject => {
  const parsed = JSON.parse(json);
  return {
    ...parsed,
    createdAt: new Date(parsed.createdAt),
    latlngs: convertSerializableToLatLngs(parsed.latlngs)
  };
};

// 坐标转换辅助函数
const convertLatLngsToSerializable = (
  latlngs: LatLngExpression[] | LatLngExpression
): any => {
  if (Array.isArray(latlngs)) {
    return latlngs.map(latlng => convertLatLngsToSerializable(latlng));
  } else if (latlngs instanceof L.LatLng) {
    return [latlngs.lat, latlngs.lng];
  }
  return latlngs;
};

const convertSerializableToLatLngs = (
  serializable: any
): LatLngExpression[] | LatLngExpression => {
  if (Array.isArray(serializable)) {
    if (Array.isArray(serializable[0])) {
      return serializable.map(
        item => convertSerializableToLatLngs(item) as LatLngExpression
      );
    } else if (
      typeof serializable[0] === "number" &&
      typeof serializable[1] === "number"
    ) {
      return L.latLng(serializable[0], serializable[1]);
    }
  }
  return serializable;
};
